﻿using System.Windows;
using System.Windows.Input;
using HandyControl.Interactivity;

namespace WPFTestSolution.Utils {
    
    /**
     * 解决 ScrollViewer 中嵌套 DataGrid, 当鼠标在 DataGrid 中会导致 ScrollViewer 不能滑动的问题.
     *
     * 
     * Bubbling scroll events from a ListView to its parent
     * https://stackoverflow.com/questions/1585462/bubbling-scroll-events-from-a-listview-to-its-parent
     *
     * Another nice solution using attached behavior. I like it because it decoples the solution from the Control.
     * Create a no scroling behavior which will catch the PreviewMouseWheel(Tunneling) event and raise a new MouseWheelEvent(Bubbling)
     *
     * 
     * Then attach the behavior to any UIElement with nested ScrollViewers case, 使用:
     * <ScrollViewer / DataGrid/ListBox...>
     *    <i:Interaction.Behaviors>
     *        <local:IgnoreMouseWheelBehavior />
     *    </i:Interaction.Behaviors>
     * </ScrollViewer / DataGrid/ListBox...>
     *
     * 
     * To anyone using this solution, you have to make sure you have added the using System.Windows.
     * Interactivity namespace, which can be added to your current project with the command Install-Package Expression.Blend.Sdk from the NuGet package manager console.
     * Also, you have to add the namespace to your .xaml file with
     * xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity".
     * – gbmhunter Jan 20, 2016 at 9:52 
     *
     * Also, System.Windows, System.Windows.Input, and System.Windows.Controls.
     * And I also found an alternate way to reference the interactivity assembly:
     * xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity".
     * – vapcguy Oct 25, 2016 at 18:04 
     *
     * Starting from .NET Core 3, you should use Microsoft.Xaml.Behaviors.Wpf NuGet package instead.
     * – Tyrrrz Nov 17, 2019 at 15:04
     *
     * Starting from .NET Core 3, you should also use
     * xmlns:i="http://schemas.microsoft.com/xaml/behaviors" in the xaml.
     * – Jinjinov Jan 12, 2021 at 16:04
     */
    public sealed class IgnoreMouseWheelBehavior : Behavior<UIElement> {
        
        protected override void OnAttached( ) {
            base.OnAttached( );
            AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel ;
        }

        protected override void OnDetaching( ) {
            AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
            base.OnDetaching( );
        }

        void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e) {
            e.Handled = true;
            var e2 = new MouseWheelEventArgs(e.MouseDevice,e.Timestamp,e.Delta) {
                RoutedEvent = UIElement.MouseWheelEvent
            };
            AssociatedObject.RaiseEvent(e2);
        }
    }
}